#include "yocto/math/fcn/integrate.hpp"
#include "yocto/math/fcn/derivative.hpp"

using namespace yocto;
using namespace math;

typedef numeric<double>::function Function;

class protons
{
public:
    protons() :
    dervs(),
    h( this, & protons::get_h  ),
    dh( this, &protons::get_dh ),
    dF( this, &protons::get_dF ),
    dG( this, &protons::get_dG )
    {
        
    }
    
    ~protons()
    {
    }
    
    
  
    
    derivative<double> dervs;
    Function           h;
    Function           dh;
    Function           dF;
    Function           dG;
    
    double get_h( double t )
    {
        return 1+2*cos(t);
    }
    
    double get_dh( double t )
    {
        return dervs( h, t, 1e-4);
    }
    
    double get_dF( double t )
    {
        return dh(t)/Q(h(t));
    }
    
    double Q(double H)
    {
        return 1+H*H;
    }
    
    double get_dG(double H)
    {
        return 1.0/Q(H);
    }
    
private:
    YOCTO_DISABLE_COPY_AND_ASSIGN(protons);
    
};


int main( int argc, char *argv[] )
{
    try 
    {
        protons   P;
        integrate<double> intg = { 1e-5 };
        const double t0 = 0;
        const double t1 = 10;
        const double I1 = intg(  t0, t1, P.dF );
        std::cerr << "I1=" << I1 << std::endl;
        
        const double h0 = P.h(t0);
        const double h1 = P.h(t1);
        const double I2 = intg( h0, h1, P.dG );
        std::cerr << "I2=" << I2 << std::endl;
        return 0;
    } 
    catch (...)
    {
        std::cerr << "Exception !" << std::endl;   
        
    }
    return -1;
}